<?php

class Upload
{
    //保存路径
    protected $savePath;
    //固定字段
    protected $field = 'file';
    //日期目录
    protected $datePath = true;
    //随机名字
    protected $randName = true;
    //允许MIME
    protected $mimes = [
        'image/png',
        'image/gif',
        'image/jpeg',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    ];
    //允许后缀
    protected $suffixes = ['png', 'jpg', 'jpeg', 'gif', 'xlsx'];
    //最大尺寸
    protected $maxSize = 2000000;
    //上传信息
    protected $uploadInfo;
    //文件名称
    protected $extName;
    //文件名称
    public $pathName;
    //错误代码
    public $errorNumber = 0;
    //错误信息
    public $errorMessage = '上传成功';
    public $urls = [];

    public function __construct($options = null)
    {
        $this->setOption($options);
    }

    public function setOption($options)
    {
        if (is_array($options)) {
            $keys = get_class_vars(__CLASS__);
            foreach ($options as $key => $value) {
                //在属性列表中才设置属性
                if (in_array($key, $keys)) {
                    $this->$key = $value;
                }
            }
        }
    }

    public function uploadFile($dir)
    {
        $this->savePath = $dir;

        //1、检查保存路径
        if (!$this->checkSavePath()) {
            return false;
        }
        //2、检查上传信息
        if (!$this->checkUploadInfo()) {
            return false;
        }
        //3、检查系统错误
        if (!$this->checkUploadError()) {
            return false;
        }
        //4、检查自定义错误
        if (!$this->checkAllowOption()) {
            return false;
        }
        //5、检车是否是上传文件
        if (!$this->checkUploadFile()) {
            return false;
        }
        //6、拼接路径名
        $this->joinPathName();
        //7、移动上传文件
        if (!$this->moveUploadFile()) {
            return false;
        }
        return true;
    }

    public function uploadFiles($dir, $fileInfo)
    {
        $this->savePath = $dir;

        //1、检查保存路径
        if (!$this->checkSavePath()) {
            return false;
        }
        //2、检查上传信息
        $this->uploadInfo = $fileInfo;

        $this->extName = pathinfo($this->uploadInfo['name'], PATHINFO_EXTENSION);;
        //3、检查系统错误
        if (!$this->checkUploadError()) {
            return false;
        }
        //4、检查自定义错误
        if (!$this->checkAllowOption()) {
            return false;
        }
        //5、检车是否是上传文件
        if (!$this->checkUploadFile()) {
            return false;
        }
        //6、拼接路径名
        $this->joinPathName();
        //7、移动上传文件
        if (!$this->moveUploadFile()) {
            return false;
        }
        return true;
    }

    protected function checkSavePath()
    {
        if (!is_dir($this->savePath)) {
            $this->errorNumber = -1;
            $this->errorMessage = '保存路径不存在';
            return false;
        }
        if (!is_writable($this->savePath)) {
            $this->errorNumber = -2;
            $this->errorMessage = '保存路径不可写';
            return false;
        }
        $this->savePath = rtrim($this->savePath, '/') . '/';
        return true;
    }

    protected function checkUploadInfo()
    {
        if (empty($_FILES[$this->field])) {
            $this->errorNumber = -3;
            $this->errorMessage = "没有{$_FILES[$this->field]}相关上传信息";
            return false;
        }
        $this->uploadInfo = $_FILES[$this->field];
        $this->extName = pathinfo($this->uploadInfo['name'], PATHINFO_EXTENSION);;
        return true;
    }

    protected function checkUploadError()
    {
        if ($this->uploadInfo['error'] == 0) {
            return true;
        }
        switch ($this->uploadInfo['error']) {
            case UPLOAD_ERR_INI_SIZE:
                $this->errorMessage = '超出了配置文件中设定文件大小';
                break;
            case UPLOAD_ERR_FORM_SIZE:
                $this->errorMessage = '超出了MAX_FILE_SIZE的大小';
                break;
            case UPLOAD_ERR_PARTIAL:
                $this->errorMessage = '只有部分文件被上传';
                break;
            case UPLOAD_ERR_NO_FILE:
                $this->errorMessage = '没有文件被上传';
                break;
            case UPLOAD_ERR_NO_TMP_DIR:
                $this->errorMessage = '没有找到临时文件夹';
                break;
            case UPLOAD_ERR_CANT_WRITE:
                $this->errorMessage = '文件写入失败';
                break;
            default:
                $this->errorMessage = '未知错误';
                break;
        }
        $this->errorNumber = $this->uploadInfo['error'];
        return false;
    }

    protected function checkAllowOption()
    {
        if (!in_array($this->uploadInfo['type'], $this->mimes)) {
            $this->errorNumber = -4;
            $this->errorMessage = '不允许的MIME:' . $this->uploadInfo['type'];
            return false;
        }
        if (!in_array($this->extName, $this->suffixes)) {
            $this->errorNumber = -5;
            $this->errorMessage = '不允许的后缀:' . $this->extName;
            return false;
        }
        if ($this->uploadInfo['size'] > $this->maxSize) {
            $this->errorNumber = -6;
            $this->errorMessage = '超出了规定大小:' . $this->maxSize . '字节';
            return false;
        }
        return true;
    }

    protected function checkUploadFile()
    {
        if (!is_uploaded_file($this->uploadInfo['tmp_name'])) {
            $this->errorNumber = -7;
            $this->errorMessage = '不是上传文件';
            return false;
        }
        return true;
    }

    protected function joinPathName()
    {
        //路径
        $this->pathName = $this->savePath;
        if ($this->datePath) {
            $this->pathName .= date('Y/m/d/');
            if (!file_exists($this->pathName)) {
                mkdir($this->pathName, 0777, true);
            }
        }
        //名字
        if ($this->randName) {
            $this->pathName .= uniqid();
        } else {
            $info = pathinfo($this->uploadInfo['name']);
            $this->pathName .= $info['filename'];
        }
        //后缀
        $this->pathName .= '.' . $this->extName;
        $serveUrl = isset($_SERVER['HTTP_HOST']) && !empty($_SERVER['HTTP_HOST']) ? "http://" . $_SERVER['HTTP_HOST'] : "http://" . $_SERVER['SERVER_NAME'];
        array_push($this->urls, "{$serveUrl}/{$this->pathName}");
    }

    protected function moveUploadFile()
    {
        if (move_uploaded_file($this->uploadInfo['tmp_name'], $this->pathName)) {
            return true;
        }
        $this->errorNumber = -8;
        $this->errorMessage = '上传文件保存';
        return false;
    }
}